package cn.wnco.conf;


import cn.wnco.anno.IAuth;
import cn.wnco.anno.IRole;
import cn.wnco.tool.JwtTool;
import cn.wnco.tool.Tmap;
import cn.wnco.tool.Uinfo;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static cn.wnco.conf.Const.*;


@Component
public class ApiInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /*HandlerMethod通常关联着基于方法级别的请求处理逻辑，
        比如 Spring MVC 里一个带@RequestMapping注解的控制器方法
        对应的处理器对象就是HandlerMethod类型）的处理对象时，就可能会出现这样的代码，
        根据不同的情况决定是否放行请求或者执行某些额外的逻辑等。*/
        if (!(handler instanceof HandlerMethod)) return true;
        //当前方法需要的权限角色
        Map<String, String> typeV = fromAnno(handler);
        //jwt
        String token = request.getHeader(key_tk);
        //当前用户拥有的权限角色
        Claims claims = JwtTool.parseToken(token);
        Uinfo uinfo = new Uinfo();
        uinfo.setCuser(claims);
        Tmap.instance().setContext(uinfo);
        //权限校验
        return permit(typeV, claims);

    }

    private boolean permit(Map<String, String> typeV, Claims claims) {
        String needAuth = typeV.get(map_auth);
        String needRole = typeV.get(map_role);
        if (!needAuth.isBlank()) {
            Object o = claims.get(map_auth);
            if (o != null) {
                List<String> str = (List<String>) o;
                return str.contains(needAuth);
            }
            return false;
        }
        if (!needRole.isBlank()) {
            Object o = claims.get(map_role);
            if (o != null) {
                List<String> str = (List<String>) o;
                return str.contains(needRole);
            }
            return false;
        }
        return false;
    }

    private Map<String, String> fromAnno(Object handler) {
        Map<String, String> map = new HashMap<>();
        if (((HandlerMethod) handler).hasMethodAnnotation(IAuth.class)) {
            String value = Objects.requireNonNull(((HandlerMethod) handler).getMethodAnnotation(IAuth.class)).value();
            map.put(map_auth, value);
        }
        if (((HandlerMethod) handler).hasMethodAnnotation(IRole.class)) {
            String value = Objects.requireNonNull(((HandlerMethod) handler).getMethodAnnotation(IRole.class)).value();
            map.put(map_role, value);
        }
        return map;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        Tmap.instance().clear();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
